package com.cskaoyan.javase.oop2._0encapsulate._0introduction;

/**
 * @description: 封装的引入
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * > 封装（encapsulate）是一种信息隐藏技术，依赖于访问权限控制符实现
 * - 所谓封装即是，隐藏对象中属性和一些实现细节，仅对外提供公共的访问方法
 *   - 广义的说类也是一种封装，指将数据和基于数据的操作封装在一起
 *   - 狭义的封装则是指借助访问权限控制符，将数据和数据操作保护在内部的一种技术
 *     - 此时系统的其他部分只有通过在数据外面的被授权的操作才能够进行交互
 *
 * - 封装的目的是将类的使用者和设计者分开
 * - 在面向对象的编程中，用类来封装相关的数据和方法，保证了数据的安全和系统的严密性
 *
 * 思考：我们之前定义的类中，都没有关注访问权限控制符，会有什么问题？
 *      如果我们不希望成员被外部访问,这时是做不到的
 *      并且外部访问的情况我们是不可控的: 1,访问的结果不可控 2,设置赋值的结果不可控
 *
 * 为了解决以上问题,我们使用访问权限修饰符,修饰成员,封装它,具体:
 *      1,既然不希望外界访问,直接私有化它
 *      2,现在外界是访问不到了,但是这样做也不是很合适,所以要给外界提供途径去访问
 *          这个时候要提供方法去访问
 *      3,对于一个成员变量而言,我们把赋值的方法称之为"setter"方法
 *          把访问取值的方法称之为"getter"方法
 *          它们的方法名取名为"setXxx"或者"getXxx"
 *
 * 如果私有化成员变量并给出相应的getter/setter方法后,访问权限反而更宽松了,这样做的目的是什么?
 *      封装并使用getter/setter方法的好处是什么?
 *
 * 1,赋值和访问从不可控变为可控
 * 2,访问的控制权限仍然在程序员手中,只需要不提供getter/setter方法,外界就不能访问了
 * 3,把代码的设计者和使用者分开了
 * 4,把成员变量的赋值和访问区分开了
 *
 * 总结一下: 在正常的开发中,多数情况下,多数普通成员变量都应该是私有的,如果想要被外界访问,提供getter/setter方法
 *      极少见可以直接访问成员变量
 *
 */
public class Demo {
    public static void main(String[] args) {
        /*Student s = new Student();
        System.out.println(s.getAge()); //0
        s.setAge(18);
        System.out.println(s.getAge());*/

        Student s = new Student(88);
        //System.out.println(s.getAge());
        s.setAge(120);
        System.out.println(s.getAge());

    }
}

class Student {
    private int age;
    private String name;
    private String gender;

    //提供访问取值的getter方法
    public int getAge() {
        return age;
    }

    //提供赋值的setter方法
    public void setAge(int age) {
        //人的年龄应该在1-130
        if (age > 1 && age < 130) this.age = age;
        else System.out.println("你成精了!");
    }

    public Student() {
    }

    public Student(int age) {
        this.age = age;
    }
}